package com.xu.ai.model.openai.controller;

import java.util.List;
import java.util.Map;

import jakarta.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.chat.evaluation.FactCheckingEvaluator;
import org.springframework.ai.chat.evaluation.RelevancyEvaluator;
import org.springframework.ai.document.Document;
import org.springframework.ai.evaluation.EvaluationRequest;
import org.springframework.ai.rag.advisor.RetrievalAugmentationAdvisor;
import org.springframework.ai.rag.retrieval.search.VectorStoreDocumentRetriever;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.vectorstore.filter.FilterExpressionBuilder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * AI 模型评估
 *
 * @author xuguan
 * @since 2025/9/30
 */
@RestController
@RequestMapping("/api/evaluator")
public class EvaluatorController {
	private static final Logger log = LoggerFactory.getLogger(EvaluatorController.class);
	private static final double SIMILARITY_THRESHOLD = 0.5d;
	private static final int TOP_K = 3;
	private final ChatClient.Builder chatClientBuilder;
	private final ChatClient chatClient;
	private final VectorStore vectorStore;

	public EvaluatorController(ChatClient.Builder chatClientBuilder,
							   VectorStore vectorStore) {
		this.chatClientBuilder = chatClientBuilder;
		this.chatClient = chatClientBuilder.build();
		this.vectorStore = vectorStore;
	}

	@PostConstruct
	public void init() {
		var searchDocuments = vectorStore.similaritySearch(
				SearchRequest.builder()
						.filterExpression(new FilterExpressionBuilder().eq("title", "中国的首都").build())
						.similarityThreshold(SIMILARITY_THRESHOLD)
						.topK(TOP_K)
						.build()
		);
		if (searchDocuments.isEmpty()) {
			var content = """
					中华人民共和国首都位于北京市，中华人民共和国成立前夕的旧称为北平，
					是中共中央及中央人民政府所在地，中央四个直辖市之一，
					全国政治、文化、国际交往和科技创新中心，中国古都、国家历史文化名城和国家中心城市之一。
					""";
			var document = new Document(content, Map.of("title", "中国的首都"));
			vectorStore.add(List.of(document));
		}
	}

	@GetMapping("/relevancy")
	public String relevancy(@RequestParam(value = "query", defaultValue = "中国的首都是哪里?") String query) {
		var ragAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
				.searchRequest(SearchRequest.builder().
						similarityThreshold(SIMILARITY_THRESHOLD).
						topK(TOP_K).
						build())
				.build();
		var chatResponse = chatClient
				.prompt()
				.advisors(ragAdvisor)
				.user(query)
				.call()
				.chatResponse();

		@SuppressWarnings("unchecked")
		var context = (List<Document>) chatResponse.getMetadata().get(QuestionAnswerAdvisor.RETRIEVED_DOCUMENTS);
		var response = chatResponse.getResult().getOutput().getText();
		var evaluationRequest = new EvaluationRequest(
				// Query
				query,
				// Context
				context,
				// Response
				response
		);

		var evaluator = RelevancyEvaluator.builder().chatClientBuilder(chatClientBuilder).build();
		var evaluationResponse = evaluator.evaluate(evaluationRequest);
		var pass = evaluationResponse.isPass();
		log.info("AI模型评估结果: {}", pass);

		return pass ? response : "暂无数据";
	}

	@GetMapping("/fact-checking")
	public String factChecking(@RequestParam(value = "query", defaultValue = "中国的首都是哪里?") String query) {
		var ragAdvisor = RetrievalAugmentationAdvisor.builder()
				.documentRetriever(VectorStoreDocumentRetriever.builder()
						.vectorStore(vectorStore)
						.similarityThreshold(SIMILARITY_THRESHOLD)
						.topK(TOP_K)
						.build())
				.build();
		var chatResponse = chatClient
				.prompt()
				.advisors(ragAdvisor)
				.user(query)
				.call()
				.chatResponse();

		final List<Document> document = chatResponse.getMetadata().get(RetrievalAugmentationAdvisor.DOCUMENT_CONTEXT);
		var claim = chatResponse.getResult().getOutput().getText();
		var evaluationRequest = new EvaluationRequest(
				// Document
				document,
				// Claim
				claim
		);

		var evaluator = FactCheckingEvaluator.builder(chatClientBuilder).build();
		var evaluationResponse = evaluator.evaluate(evaluationRequest);
		var pass = evaluationResponse.isPass();
		log.info("AI模型评估结果: {}", pass);

		return pass ? claim : "暂无数据";
	}
}
